import asyncio
import json

import datetime
from tornado import gen, locks
from baseHandler import Application, PayHandler, init_logger, http_result
from util import cerid_check
import pymongo
import motor

logger = init_logger("unionpayquick", "/app/log/unionpay/unionpayquick.log")
lock = locks.Lock()


class QuickCredit(PayHandler):
    @gen.coroutine
    def get(self):
        logger.info(self.request.path)

        if self.request.path == '/pay/unionpay/quickpay':
            biz_id = 'PAY.UNIONPAY.QUICK.DEBIT'
            func_code = '200101'
            pn_req = 'PAY_UNIONPAY_QUICK_DEBIT_REQ'
            pn_res = 'PAY_UNIONPAY_QUICK_DEBIT_RES'
        elif self.request.path == '/pay/unionpay/gateway':
            biz_id = 'PAY.UNIONPAY.GATEWAY'
            func_code = '200101'
            pn_req = 'PAY_UNIONPAY_QUICK_DEBIT_REQ'
            pn_res = 'PAY_UNIONPAY_QUICK_DEBIT_RES'
        else:
            return self.write(json.dumps({"message": "未知错误", "ret": -1}))
        exited = yield self.merchant_exit()
        if not exited:
            logger.info("商户不存在")
            return self.write(json.dumps({"message": "商户不存在", "ret": -1}))
        if not self.check_ip():
            return self.write(json.dumps({"message": "ip错误", "ret": -1}))
        if not self.check_sign():
            logger.info("签名验证失败")
            return self.write(json.dumps({"message": "签名验证失败", "ret": -1}))
        data = self.decrypt()
        if not data:
            return self.write({"message": "解密失败", "ret": -1})
        data = json.loads(data)
        logger.info(data)

        # arguments = ["ordernumber", "amount", "username", "userpid", "usercardno", "usertel"]
        # for arg in arguments:
        #     if arg not in data:
        #         return self.write({"ret": -1, "message": "缺少%s" % arg})

        res = self.check_ordernumber(data)
        if res:
            return self.write(res)
        # ret, msg = cerid_check.checkIdcard(data['userpid'])
        # if ret !=0:
        #     return self.write({"ret": -1, "message": msg})
        amount = data["amount"]
        if not isinstance(amount, str) or not amount.isdigit():
            return self.write({"ret": -1, "message": "amount 格式错误"})
        # usercardno = data["usercardno"]
        # if not isinstance(usercardno, str) or len(usercardno) >19 or not usercardno.isdigit():
        #     return self.write({"ret": -1, "message": "creditcardno 格式错误"})
        # usertel = data["usertel"]
        # if not isinstance(usertel, str) or len(usertel) >20 or not usertel.isdigit():
        #     return self.write({"ret": -1, "message": "usertel 格式错误"})
        logger.info('%s|银联快捷|订单%s|金额%s', self.merchantid, data["ordernumber"], data["amount"])
        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "MPAY",
            "FUNCCODE": func_code,
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                "MERCHANTID": str(self.merchantid),
                "MERCHANTORDERNO": str(data["ordernumber"]),
                "OPMONEY": str(data["amount"]),
                "BIZID": biz_id,
                "USERNAME": data.get('username', "none"),
                "USERPID": data.get('userpid', 'none'),
                "CARDNO": data.get("usercardno", "6222023602098888888"),
                "USERTEL": data.get('usertel', 'none'),
                "NOTIFYURL": data.get("backurl", ""),
                "RETURNURL": data.get("returnurl", ""),
                "CLIENTIP": self.remote_ip,
            }
        }
        logger.info(input_json)
        core_response = yield from self.pay_core(pn_req, input_json)
        logger.info(core_response)

        if core_response['RETREDIRECT'] == "PAY.CORE.EBS":
            logger.info('%s|银联卡收款|订单%s|-1|%s', self.merchantid, data["ordernumber"], core_response["MESSAGE"])
            return self.write({"ret": -1, "message": core_response["MESSAGE"]})
        else:
            channel = yield self.get_channel_redis(core_response['PAYCHANNEL'])
            # if self.request.path == '/pay/unionpay/quick/facepay':
            #     channel = 'http://127.0.0.1:10029/jiupai/rpm_quick_pay_init'
            logger.info(channel)
            request_obj = core_response
            request_obj.update(data)
            # 发送到渠道
            response = yield http_result(channel, request_obj)
        logger.info(response.body)
        if response.code == 200 and response.body.startswith(b'{'):
            channel_result = json.loads(response.body.decode("utf-8"))
            orderstate = channel_result["orderstate"]
            logger.info('%s|银联快捷|订单%s|支付结果%s', self.merchantid, data['ordernumber'], orderstate)

        else:
            orderstate = "1"
            message = response.body.decode('utf-8') if response.code == 200 else "未知错误"
            channel_result = {"message": message}
            logger.info('%s|银联快捷|订单%s|支付结果%s|%s', self.merchantid, data['ordernumber'], orderstate, message)

        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "RESP",
            "FUNCCODE": func_code,
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                "OUTERORDERNO": core_response["OUTERORDERNO"],
                # "OPMONEY": str(core_response["OPMONEY"]),
                "PAYORDERNO": core_response["OUTERORDERNO"],
                "ORDERSTATE": orderstate,
                "PAYINFO": channel_result.get('message') or 'none',
            }
        }
        logger.info(input_json)
        result = yield from self.pay_core(pn_res, input_json)
        logger.info(result)
        result.update({"MERCHANTID": self.merchantid})
        if result["MESSAGE"] == 'SUCCESS':

            return self.write(channel_result.get("payinfo") or "下单失败")
        else:
            return self.write({"ret": -1, "message": result['MESSAGE']})

    @gen.coroutine
    def post(self):
        logger.info(self.request.path)

        if self.request.path == '/pay/unionpay/quickpay':
            biz_id = 'PAY.UNIONPAY.QUICK.DEBIT'
            func_code = '200101'
            pn_req = 'PAY_UNIONPAY_QUICK_DEBIT_REQ'
            pn_res = 'PAY_UNIONPAY_QUICK_DEBIT_RES'
        elif self.request.path == '/pay/unionpay/gateway':
            biz_id = 'PAY.UNIONPAY.GATEWAY'
            func_code = '200101'
            pn_req = 'PAY_UNIONPAY_QUICK_DEBIT_REQ'
            pn_res = 'PAY_UNIONPAY_QUICK_DEBIT_RES'
        else:
            return self.write(json.dumps({"message": "未知错误", "ret": -1}))
        exited = yield self.merchant_exit()
        if not exited:
            logger.info("商户不存在")
            return self.write(json.dumps({"message": "商户不存在", "ret": -1}))
        if not self.check_ip():
            return self.write(json.dumps({"message": "ip错误", "ret": -1}))
        if not self.check_sign():
            logger.info("签名验证失败")
            return self.write(json.dumps({"message": "签名验证失败", "ret": -1}))
        data = self.decrypt()
        if not data:
            return self.write({"message": "解密失败", "ret": -1})
        data = json.loads(data)
        logger.info(data)
        # arguments = ["ordernumber", "amount", "username", "userpid", "usercardno", "usertel"]
        # for arg in arguments:
        #     if arg not in data:
        #         return self.write({"ret": -1, "message": "缺少%s" % arg})

        res = self.check_ordernumber(data)
        if res:
            return self.write(res)
        # ret, msg = cerid_check.checkIdcard(data['userpid'])
        # if ret !=0:
        #     return self.write({"ret": -1, "message": msg})
        amount = data["amount"]
        if not isinstance(amount, str) or not amount.isdigit():
            return self.write({"ret": -1, "message": "amount 格式错误"})
            # usercardno = data["usercardno"]
            # if not isinstance(usercardno, str) or len(usercardno) >19 or not usercardno.isdigit():
            return self.write({"ret": -1, "message": "creditcardno 格式错误"})
        # usertel = data["usertel"]
        # if not isinstance(usertel, str) or len(usertel) >20 or not usertel.isdigit():
        #     return self.write({"ret": -1, "message": "usertel 格式错误"})
        logger.info('%s|银联快捷|订单%s|金额%s', self.merchantid, data["ordernumber"], data["amount"])
        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "MPAY",
            "FUNCCODE": func_code,
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                "MERCHANTID": str(self.merchantid),
                "MERCHANTORDERNO": str(data["ordernumber"]),
                "OPMONEY": str(data["amount"]),
                "BIZID": biz_id,
                "USERNAME": data.get('username', "none"),
                "USERPID": data.get('userpid', 'none'),
                "CARDNO": data.get("usercardno", '6222023602098888888'),
                "USERTEL": data.get('usertel', 'none'),
                "NOTIFYURL": data.get("backurl", ""),
                "RETURNURL": data.get("returnurl", ""),
                "CLIENTIP": self.remote_ip,
            }
        }
        logger.info(input_json)
        core_response = yield from self.pay_core(pn_req, input_json)
        logger.info(core_response)

        if core_response['RETREDIRECT'] == "PAY.CORE.EBS":
            logger.info('%s|银联卡收款|订单%s|-1|%s', self.merchantid, data["ordernumber"], core_response["MESSAGE"])
            return self.write({"ret": -1, "message": core_response["MESSAGE"]})
        else:
            channel = yield self.get_channel_redis(core_response['PAYCHANNEL'])
            # if self.request.path == '/pay/unionpay/quick/facepay':
            #     channel = 'http://127.0.0.1:10029/jiupai/rpm_quick_pay_init'
            logger.info(channel)
            request_obj = core_response
            request_obj.update(data)
            # 发送到渠道
            response = yield http_result(channel, request_obj)
        logger.info(response.body)
        if response.code == 200 and response.body.startswith(b'{'):
            channel_result = json.loads(response.body.decode("utf-8"))
            orderstate = channel_result["orderstate"]
            logger.info('%s|银联快捷|订单%s|支付结果%s', self.merchantid, data['ordernumber'], orderstate)

        else:
            orderstate = "1"
            message = response.body.decode('utf-8') if response.code == 200 else "未知错误"
            channel_result = {"message": message}
            logger.info('%s|银联快捷|订单%s|支付结果%s|%s', self.merchantid, data['ordernumber'], orderstate, message)

        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "RESP",
            "FUNCCODE": func_code,
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                "OUTERORDERNO": core_response["OUTERORDERNO"],
                # "OPMONEY": str(core_response["OPMONEY"]),
                "PAYORDERNO": core_response["OUTERORDERNO"],
                "ORDERSTATE": orderstate,
                "PAYINFO": channel_result.get('message', 'success'),
            }
        }
        result = yield from self.pay_core(pn_res, input_json)
        logger.info(result)
        result.update({"MERCHANTID": self.merchantid})
        if result["MESSAGE"] == 'SUCCESS':
            rsp_obj = {
                'ordernumber': result['MERCHANTORDERNO'],
                "payorderno": result["OUTERORDERNO"],
                "resptime": result['RESPTIME'],
                "orderstate": orderstate,
                "payinfo": channel_result.get("payinfo"),
                "message": channel_result.get("message"),
            }
            return_data = self.niti_data(rsp_obj, result)
            return_data.update({"ret": 0, 'message': "success"})
            return self.write(return_data)
        else:
            return self.write({"ret": -1, "message": result['MESSAGE']})


class FrontEntrust(PayHandler):
    @gen.coroutine
    def post(self):
        logger.info(self.request.path)
        biz_id = 'PAY.UNIONPAY.ENTRUST'
        exited = yield self.merchant_exit()
        if not exited:
            logger.info("商户不存在")
            return self.write(json.dumps({"message": "商户不存在", "ret": -1}))
        if not self.check_ip():
            return self.write(json.dumps({"message": "ip错误", "ret": -1}))
        if not self.check_sign():
            logger.info("签名验证失败")
            return self.write(json.dumps({"message": "签名验证失败", "ret": -1}))
        data = self.decrypt()
        if not data:
            return self.write({"message": "解密失败", "ret": -1})
        data = json.loads(data)
        logger.info(data)

        # arguments = ["ordernumber", "amount", "username", "userpid", "usercardno"]
        # for arg in arguments:
        #     if arg not in data:
        #         return self.write({"ret": -1, "message": "缺少%s" % arg})


        res = self.check_ordernumber(data)
        if res:
            return self.write(res)

        if data.get("settle_type") == 'BANK_PAY_DAILY_ORDER':
            biz_id = 'PAY.UNIONPAY.ENTRUST.T1'
        elif data.get("settle_type") == 'BANK_PAY_MAT_ENDOWMENT_ORDER':
            biz_id = 'PAY.UNIONPAY.ENTRUST'
        else:
            return self.write({"message": "代付类型不存在", "ret": -1})
        # ret, msg = cerid_check.checkIdcard(data['userpid'])
        # if ret !=0:
        #     return self.write({"ret": -1, "message": msg})
        amount = data["amount"]
        if not isinstance(amount, str) or not amount.isdigit():
            return self.write({"ret": -1, "message": "amount 格式错误"})
        usercardno = data["usercardno"]
        if not isinstance(usercardno, str) or len(usercardno) > 19 or not usercardno.isdigit():
            return self.write({"ret": -1, "message": "creditcardno 格式错误"})

        logger.info('%s|银联快捷代付|订单%s|金额%s', self.merchantid, data["ordernumber"], data["amount"])
        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "MPAY",
            "FUNCCODE": "200106",
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                "MERCHANTID": str(self.merchantid),
                "MERCHANTORDERNO": str(data["ordernumber"]),
                "OPMONEY": str(data["amount"]),
                "BIZID": biz_id,
                "CUSTNAME": data['username'],
                "CERDTYPE": "01",
                "CERDID": data.get('userpid', 'none'),
                "CARDNO": data["usercardno"],
                "NOTIFYURL": data.get("backurl", ""),
                "RETURNURL": data.get("returnurl", ""),
                "CLIENTIP": self.remote_ip,
                "BANKUNION": data.get('bankunion', ''),
                "PAYSOURE": "CP01",

                # "CUSTNAME": data["accountname"],

            }
        }
        logger.info(input_json)
        core_response = yield from self.pay_core('PAY_UNIONPAY_ENTRUST_REQ', input_json)
        logger.info(core_response)

        if core_response['RETREDIRECT'] == "PAY.CORE.EBS":
            logger.info('%s|银联快捷代付|订单%s|-1|%s', self.merchantid, data["ordernumber"], core_response["MESSAGE"])
            return self.write({"ret": -1, "message": core_response["MESSAGE"]})

        channel = yield self.get_channel_redis(core_response['PAYCHANNEL'])
        logger.info(channel)
        # request_obj = core_response
        data.update(core_response)
        # 发送到渠道
        response = yield http_result(channel, data)
        logger.info(response.body)
        if response.code == 200 and response.body.startswith(b'{'):
            channel_result = json.loads(response.body.decode("utf-8"))
            orderstate = channel_result["orderstate"]
            logger.info('%s|银联快捷代付|订单%s|支付结果%s', self.merchantid, data['ordernumber'], orderstate)

        else:
            orderstate = "1"
            message = response.body.decode('utf-8') if response.code == 200 else "未知错误"
            channel_result = {"message": message}
            logger.info('%s|银联快捷代付|订单%s|支付结果%s|%s', self.merchantid, data['ordernumber'], orderstate, message)

        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "RESP",
            "FUNCCODE": "200106",
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                "OUTERORDERNO": core_response["OUTERORDERNO"],
                # "OPMONEY": str(core_response["OPMONEY"]),
                "PAYORDERNO": core_response["OUTERORDERNO"],
                "ORDERSTATE": orderstate,
                "PAYINFO": channel_result.get('message', 'success'),
            }
        }
        logger.info(input_json)
        result = yield from self.pay_core("PAY_UNIONPAY_ENTRUST_RES", input_json)
        logger.info(result)
        result.update({"MERCHANTID": self.merchantid})
        if result["MESSAGE"] == 'SUCCESS':
            rsp_obj = {
                'ordernumber': result['MERCHANTORDERNO'],
                "payorderno": result["OUTERORDERNO"],
                "amount": data['amount'],
                "orderstate": orderstate,
                "payinfo": channel_result.get("message", "")
            }
            return_data = self.niti_data(rsp_obj, result)
            return_data.update({"ret": 0, 'message': "success"})
            return self.write(return_data)
        else:
            return self.write({"ret": -1, "message": result['MESSAGE']})


if __name__ == "__main__":
    handlers = [
        (r"/pay/unionpay/quickpay", QuickCredit),
        (r"/pay/unionpay/gateway", QuickCredit),
        (r"/pay/unionpay/entrust", FrontEntrust),
    ]

    logger.info("Run unionpay server ... http://127.0.0.1:9992")
    application = Application(handlers)
    application.listen(9992, address="127.0.0.1")
    client = motor.motor_tornado.MotorClient('localhost', 27017, username='slcore',
                                             password='c3e57532ada96706734f110a8678bb68')
    mongo_db = client.jiupai
    loop = asyncio.get_event_loop()
    application.init_with_loop(loop)
    loop.run_forever()
